
	#include "ExpansionBoardComm.h"

/******************************************************************************
*							LOCAL MACRO DEFINITIONS
******************************************************************************/
	
/******************************************************************************
*   Local Type Definitions
******************************************************************************/
	enum{
		STATEA=0,
		STATE0,
		STATE1,
		STATE2,
		MAXSTATE
	};
		
/******************************************************************************
*   Global Variable Definitions
******************************************************************************/
	PrecisionNumber EnvTemperature,EnvRHumidity;
	unsigned char   COGas,O3Gas,ExpBoardInfo;
	
	unsigned char Message_Type=MESSAGE_TYPE1;
	unsigned char DataCounter;
	
	unsigned char ExpansionBoardData[MESSAGE_LENGTH_EB];	//Data Buffer received from Expansion Board 
	unsigned char QuaXcopterData[MESSAGE_LENGTH_EB];		//Data Buffer to be sent to Expansion Board 
	unsigned char SPITXBuffer[PACKAGE_LENGTH_EB];		//Buffer that contains the Package to be send by SPI module	
	unsigned char SPIRXBuffer[PACKAGE_LENGTH_EB];		//Buffer that contain the Package received by SPI module
	volatile char PackageDataCounter;					//Number of byte received from the SPI Slave
	SPISM SPISendDataSM;
 
/******************************************************************************
*   Local Function Declarations
******************************************************************************/
	void (* const SPITransmitData[])(void);

/******************************************************************************
*   Static Variable Definitions
******************************************************************************/
	unsigned char DataTXCounter=0;
/******************************************************************************
*   Global and Static Function Definitions
******************************************************************************/
/*****************************************************************************
 * Function: 	VfnExpansionBoardComm
 * Description: Controls the state machine to send all data through SSI module
 * Parameters:	N/A
 * Caveats:		It has to be call it several time to get the task done
 * Return:		1 - When Data has been Received, 0 - Still sending and receiving
 *****************************************************************************/	
	unsigned char VfnExpansionBoardComm(void)
	{
		if(SPISendDataSM.ActualState == STATEA)
		{
			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4,ATTENTION_PIN);
		}
		SPITransmitData[SPISendDataSM.ActualState]();
		if(SPISendDataSM.ActualState == MAXSTATE)
		{
			SPISendDataSM.ActualState = STATEA;
			PackageDataCounter=0;
			DataTXCounter=0;
			GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_4,0x00);
			return 1;	
		}
		else
		{
			return 0;
		}
	}

/*****************************************************************************
 * Function: 	VfnSPIReadRXBuffer
 * Description: Read the RX FIFO Buffer from the SPI Module
 * Parameters:	FIFOBuffer is a pointer to a storage location for data that was received over the SSI interface
 * 				Counter - number of data received 
 * Caveats:		Developed for RX Interruption service handler.
 * Return:		Number of data received.
 *****************************************************************************/		
	unsigned char VfnSPIReadRXBuffer( void )
	{
		volatile unsigned char DataFlag=0;
		
		while(SSIDataGetNonBlocking(SSI1_BASE,(unsigned long*)&SPIRXBuffer[PackageDataCounter]))
		{
			PackageDataCounter++;
		}
		return PackageDataCounter;
	}

/*****************************************************************************
 * Function: 	VfnSPIValidateData
 * Description: Validate Package data, by calculating CheckSum and compare it 
 * 				with the Package's Checksum. Then it cheks if Package HEADERS 
 * 				are corrrect
 * Parameters:	N/A
 * Caveats:		N/A.
 * Return:		0 - CheckSum Validation Fail, 1 - CheckSum Validation OK, 2 - HEADERS incorrect.
 *****************************************************************************/		
	unsigned char VfnSPIValidateData( void )
	{
		#if CHECKSUM_FORMAT	== UNSIGNED_CHAR
		volatile unsigned char CalcCheckSum,Counter; 
		CalcCheckSum = VfnUnCharCheckSum(&SPIRXBuffer[DATA_POSITION],(DATA_LENGTH));
		Counter = 0;
		while(Counter != HEADER_LENGTH)
		{
			if(SPIRXBuffer[Counter] != SPITXBuffer[Counter])
			{
				return (2);	
			}
			Counter++;	
		}
		if(CalcCheckSum == SPIRXBuffer[PACKAGE_LENGTH-1])
		{
			Counter = 0;
			while(Counter != DATA_LENGTH)
			{
				ExpansionBoardData[Counter] = SPIRXBuffer[Counter + 4];
				Counter++;
			}
			return (1);
		}
		else
		{
			return (0);	
		}	
		#endif
		
		#if CHECKSUM_FORMAT	== UNSIGNED_SHORT
		volatile unsigned short CalcCheckSum,CheckSum,Counter; 
		CalcCheckSum = VfnCheckSum16(&SPIRXBuffer[0],(MESSAGE1_LENGTH));
		Counter = 0;
		CheckSum = (SPIRXBuffer[PACKAGE1_LENGTH-3]<<8) | SPIRXBuffer[PACKAGE1_LENGTH-2]; 
		if(CalcCheckSum == CheckSum)
		{
			Counter = 0;
			while(Counter != (MESSAGE1_LENGTH - 3))
			{
				ExpansionBoardData[Counter] = SPIRXBuffer[Counter + HEADER_LENGTH];
				Counter++;
			}
			return (1);
		}
		else
		{
			return (0);	
		}
		#endif
	}
	
/*****************************************************************************
 * Function: 	VfnSSIModuleInitialization
 * Description: SSI module init. depending on H file config section and function
 * 				parameters
 * Parameters:	Module, Frequency  and DataSize (Numbre of bits of each data)
 * Caveats:		If different LM3Sxxx microcntroller is used check PORT PINS config
 * Return:		N/A
 *****************************************************************************/	
	void VfnSSIModuleInitialization(unsigned char Module,unsigned long Frequency,unsigned char DataSize)
	{
		if(Module == SSI0_MODULE)
		{
			  //
    		// The SSI0 peripheral must be enabled for use.
    		//
    		SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);

    		//
    		// For this example SSI0 is used with PortA[5:2].  The actual port and pins
    		// used may be different on your part, consult the data sheet for more
    		// information.  GPIO port A needs to be enabled so these pins can be used.
    		// TODO: change this to whichever GPIO port you are using.
    		//
    		SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    		//
    		// Configure the pin muxing for SSI0 functions on port A2, A3, A4, and A5.
    		// This step is not necessary if your part does not support pin muxing.
    		// TODO: change this to select the port/pin you are using.
    		//
    		GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    		GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    		GPIOPinConfigure(GPIO_PA4_SSI0RX);
    		GPIOPinConfigure(GPIO_PA5_SSI0TX);

    		//
    		// Configure the GPIO settings for the SSI pins.  This function also gives
    		// control of these pins to the SSI hardware.  Consult the data sheet to
    		// see which functions are allocated per pin.
    		// The pins are assigned as follows:
    		//      PA5 - SSI0Tx
    		//      PA4 - SSI0Rx
    		//      PA3 - SSI0Fss
    		//      PA2 - SSI0CLK
    		// TODO: change this to select the port/pin you are using.
    		//
    		GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 |
                   GPIO_PIN_2);

    		//
    		// Configure and enable the SSI port for SPI master mode.  Use SSI0,
   		 	// system clock supply, idle clock level low and active low clock in
    		// freescale SPI mode, master mode, 1MHz SSI frequency, and 8-bit data.
    		// For SPI mode, you can set the polarity of the SSI clock when the SSI
    		// unit is idle.  You can also configure what clock edge you want to
    		// capture data on.  Please reference the datasheet for more information on
    		// the different SPI modes.
    		//
    		SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI0_FRAME_FORMAT,SSI_MODE_MASTER, Frequency, DataSize);

			if( SPI0_INTERRUPTION == 1)
			{
				SSIIntEnable(SSI0_BASE,SPI0_INTERRUPTION_SERVICE);	
			}
   			 //
    		// Enable the SSI0 module.
    		//
    		SSIEnable(SSI0_BASE);

    		//
    		// Read any residual data from the SSI port.  This makes sure the receive
    		// FIFOs are empty, so we don't read any unwanted junk.  This is done here
    		// because the SPI SSI mode is full-duplex, which allows you to send and
    		// receive at the same time.  The SSIDataGetNonBlocking function returns
    		// "true" when data was returned, and "false" when no data was returned.
    		// The "non-blocking" function checks if there is any data in the receive
    		// FIFO and does not "hang" if there isn't.
    		//
    		unsigned long ulTemp;
     		while(SSIDataGetNonBlocking(SSI0_BASE, &ulTemp) != 0);
			
		}
		if(Module == SSI1_MODULE)
		{
			//
    		// The SSI1 peripheral must be enabled for use.
    		//
    		SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);

    		//
    		// For this example SSI0 is used with PortE[0:3].  The actual port and pins
   		 	// used may be different on your part, consult the data sheet for more
   			// information.  GPIO port E needs to be enabled so these pins can be used.
    		// TODO: change this to whichever GPIO port you are using.
    		//
    		SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

    		//
    		// Configure the pin muxing for SSI0 functions on port E0, E1, E2, and E3.
    		// This step is not necessary if your part does not support pin muxing.
    		// TODO: change this to select the port/pin you are using.
    		//
    		GPIOPinConfigure(GPIO_PE0_SSI1CLK);
    		GPIOPinConfigure(GPIO_PE1_SSI1FSS);
    		GPIOPinConfigure(GPIO_PE2_SSI1RX);
    		GPIOPinConfigure(GPIO_PE3_SSI1TX);

    		//
    		// Configure the GPIO settings for the SSI pins.  This function also gives
    		// control of these pins to the SSI hardware.  Consult the data sheet to
    		// see which functions are allocated per pin.
    		// The pins are assigned as follows:
    		//      PE3 - SSI0Tx
    		//      PE2 - SSI0Rx
    		//      PE1 - SSI0Fss
    		//      PE0 - SSI0CLK
    		// TODO: change this to select the port/pin you are using.
    		//
    		GPIOPinTypeSSI(GPIO_PORTE_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1 |GPIO_PIN_0);

    		//
    		// Configure and enable the SSI port for SPI master mode.  Use SSI0,
    		// system clock supply, idle clock level low and active low clock in
    		// freescale SPI mode, master mode, Hz SSI frequency, and 8-bit data.
    		// For SPI mode, you can set the polarity of the SSI clock when the SSI
    		// unit is idle.  You can also configure what clock edge you want to
   			 // capture data on.  Please reference the datasheet for more information on
    		// the different SPI modes.
    		//
    		SSIConfigSetExpClk(SSI1_BASE, SysCtlClockGet(), SSI1_FRAME_FORMAT,SSI_MODE_MASTER, Frequency, DataSize);

			if( SPI1_INTERRUPTION == 1)
			{
				SSIIntEnable(SSI1_BASE, SSI_RXFF );
				//SSIIntEnable(SSI1_BASE, SSI_RXTO );
				//SSIIntEnable(SSI1_BASE, SSI_RXOR );
				IntEnable(INT_SSI1); 
				//SSIIntEnable(SSI1_BASE,SPI1_INTERRUPTION_SERVICE);	
			}
			
    		//
    		// Enable the SSI1 module.
    		//
    		SSIEnable(SSI1_BASE);
    		unsigned long ulTemp;
     		while(SSIDataGetNonBlocking(SSI1_BASE, &ulTemp) != 0);
		}
	}
	
	void VfnAttentionPin(void)
	{
		SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
		GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,GPIO_PIN_4);
	}
/******************************************************************************
*   LOCAL Function Definitions
******************************************************************************/
	//////////////////////////////////////////////////////////////
	//				STATE MACHINE TO SEND DATA I2C				//
	//////////////////////////////////////////////////////////////
/*****************************************************************************
 * Function: 	VfnSendDataStateA
 * Description: Load Data into the SPITXBuffer
 * Parameters:	N/A
 * Caveats:		Non
 * Return:		N/A
 *****************************************************************************/	
	void VfnSPISendDataStateA (void)
	{
		volatile unsigned short CheckSum;
		unsigned char count=0;
		SPITXBuffer[0] = HEADER;
		SPITXBuffer[1] = MESSAGE_TYPE1;
		SPITXBuffer[2] = MESSAGE1_LENGTH;
		// fill entire data section with 0xFF
		while(count != (MESSAGE1_LENGTH-3))
		{
			SPITXBuffer[3+count] = 0xFF;
			count++;
		}
		// Calculate CHKSUM and incorporated to Package then add end message character
		CheckSum = VfnCheckSum16(&SPITXBuffer[0],(MESSAGE1_LENGTH+HEADER_LENGTH));
		SPITXBuffer[PACKAGE1_LENGTH -3] = (unsigned char)(((CheckSum) & 0xFF00)>>8);
		SPITXBuffer[PACKAGE1_LENGTH -2] = (unsigned char)(CheckSum & 0x00FF);
		SPITXBuffer[PACKAGE1_LENGTH -1] = MESSAGE_END;
		
		SPISendDataSM.ActualState = STATE0;
	}
	
/*****************************************************************************
 * Function: 	VfnSendDataState0
 * Description: Write To SPI Transmit buffer all the Data
 * Parameters:	N/A
 * Caveats:		Non
 * Return:		N/A
 *****************************************************************************/	
	void VfnSPISendDataState0 (void)
	{

		unsigned char Flag=0;	
		Flag = SSIDataPutNonBlocking(SSI1_BASE,(unsigned long)SPITXBuffer[DataTXCounter]);
		//checi if SPITXBuffer[DataTXCounter] was successfuly added into SPI FIFO buffer
		if(Flag == 1)
		{
			DataTXCounter++;
		}
		if(DataTXCounter == (PACKAGE1_LENGTH))
		{
			SPISendDataSM.ActualState = STATE2;
			SPISendDataSM.NextState   = STATE1;	
		}
	}
	
/*****************************************************************************
 * Function: 	VfnSendDataState1
 * Description: Read Data from the Receive Buffer
 * Parameters:	N/A
 * Caveats:		Non
 * Return:		N/A
 *****************************************************************************/	
	void VfnSPISendDataState1 (void)
	{
		volatile unsigned char DataFlag=0;
		volatile char Aux;
		if(PackageDataCounter == (PACKAGE1_LENGTH))
		{
			SPISendDataSM.ActualState = MAXSTATE;	
		}
		else
		{
//			while(SSIDataGetNonBlocking(SSI1_BASE,(unsigned long*)&SPIRXBuffer[PackageDataCounter]))
//			{
//				PackageDataCounter++;
//			}
//			if(PackageDataCounter == (PACKAGE1_LENGTH))
//			{
//				SPISendDataSM.ActualState = MAXSTATE;	
//			}
			Aux = PackageDataCounter;
			DataFlag  = (unsigned char)SSIDataGetNonBlocking(SSI1_BASE,(unsigned long*)&SPIRXBuffer[PackageDataCounter]);
			PackageDataCounter = Aux;
			if(DataFlag == 1)
			{
				PackageDataCounter++;
			}
			if(PackageDataCounter == (PACKAGE1_LENGTH))
			{
				SPISendDataSM.ActualState = MAXSTATE;	
			}	
		}

	}
	
/*****************************************************************************
 * Function: 	VfnSendDataState2
 * Description: wait until All data 
 * Parameters:	N/A
 * Caveats:		Non
 * Return:		N/A
 *****************************************************************************/	
	void VfnSPISendDataState2 (void)
	{
		if(!SSIBusy(SSI1_BASE))
		{
			SPISendDataSM.ActualState = SPISendDataSM.NextState;
		}
	}	
/*****************************************************************************
 * Function: 	void (* const SPITransmitData[])(void)
 * Description: Functions array. representing each state.
 * Parameters:	N/A
 * Caveats:		Non
 * Return:		N/A
 *****************************************************************************/		
	void (* const SPITransmitData[])(void)	=
	{
		VfnSPISendDataStateA,
		VfnSPISendDataState0,
		VfnSPISendDataState1,
		VfnSPISendDataState2,

	};
